﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Web;

namespace Mondial2014.Utils
{
    public static class EventDispatcher
    {
        [AttributeUsage(AttributeTargets.Method)]
        public class SubscribeAttribute : Attribute
        {
        }

        private static readonly IDictionary<Type, Collection<MethodInfo>> Subscribers = new Dictionary<Type, Collection<MethodInfo>>();

        public static void SubscribeAll()
        {
            foreach (var type in typeof(EventDispatcher).Assembly.GetTypes())
            {
                foreach (var methodInfo in type.GetMethods(BindingFlags.Static | BindingFlags.Public)
                                            .Where(m => 
                                                m.GetCustomAttributes(typeof(SubscribeAttribute)).Any() && 
                                                m.GetParameters().Count() == 1))
                {
                    var eventType = methodInfo.GetParameters().Single().ParameterType;
                    if (!Subscribers.ContainsKey(eventType))
                    {
                        Subscribers.Add(eventType, new Collection<MethodInfo>());
                    }
                    Subscribers[eventType].Add(methodInfo);
                }
            }
        }

        public static void PostEvent(object eventInstance)
        {
            if (Subscribers.ContainsKey(eventInstance.GetType()))
            {
                Task.Factory.StartNew(() =>
                {
                    foreach (var subscriber in Subscribers[eventInstance.GetType()])
                    {
                        subscriber.Invoke(null, new[] { eventInstance });
                    }
                });   
            }
        }
    }
}